﻿/*
 * HexBase.cs
 *
 * Created on November 25, 2007, 2:19 PM
 *
 * Copyright (C) 2007-2008  Hylke van der Schaaf
 * Copyright (C) 2010       Mathijs Miermans
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, in version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

using HexTD.tower;
using HexTD.util;

namespace HexTD.hex
{
	public class HexBase : Hex
	{
		public static int BASE = 1;
		public static int EMPTY = 2;
		public static int PATH = 3;

		protected char shortName;
		protected int type;
		protected int x;
		protected int y;

		protected float paintScale;
		protected float xFloat, yFloat;
		protected float xPaint, yPaint;
		protected float wFloat, hFloat;
		protected float wPaint, hPaint;

		private float[,] points;

		protected Polyline polyHex;
		protected Brush stroke1;
		protected Brush stroke2;
		protected GeometryGroup bordersE;
		protected Color borderColor;
		protected Color borderEmptyColor;
		protected Color fillColor;
		protected Color highlightOK;
		protected Color highlightNOK;
		private Color rangeColor;

		protected Context context;
		protected highlightType highlight = highlightType.none;
		private float highlightRange = 0;
		private EllipseGeometry rangeCircle;

		private bool free = true;
		private Tower tower = null;

		/** Creates a new instance of HexBase */
		public HexBase(int x, int y, Context context, bool buildable)
		{
			Color tempColor;
			// even or odd
			this.x = x;
			this.y = y;
			this.context = context;
			this.borderColor = this.context.colors.getColorBaseHexBorder();

			tempColor = this.context.colors.getColorBaseHexBackGround();
			this.fillColor = Color.FromArgb(125, tempColor.R, tempColor.G, tempColor.B);
			this.borderEmptyColor = this.context.colors.getColorBaseEmptyHexBorder();
			tempColor = this.context.colors.getColorHighlightOK();
			this.highlightOK = Color.FromArgb(125, tempColor.R, tempColor.G, tempColor.B);
			tempColor = this.context.colors.getColorHighlightNOK();
			this.highlightNOK = Color.FromArgb(125, tempColor.R, tempColor.G, tempColor.B);
			this.rangeColor = this.context.colors.getColorRangeCircle();
			this.type = HexBase.BASE;
			this.shortName = 'b';
			this.free = buildable;
		}

		public void setLocation(int x, int y)
		{
			this.x = x;
			this.y = y;
		}

		public int[] getLocation()
		{
			int[] retVal = new int[2];
			retVal[0] = this.x;
			retVal[1] = this.y;
			return retVal;
		}

		public float[] getFloatLocation()
		{
			float[] returnVal = new float[2];
			returnVal[0] = this.xFloat;
			returnVal[1] = this.yFloat;
			return returnVal;
		}
		public float[] getPaintLocation()
		{
			float[] returnVal = new float[2];
			returnVal[0] = this.xPaint;
			returnVal[1] = this.yPaint;
			return returnVal;
		}

		public bool hasTower()
		{
			return (this.tower != null);
		}

		public void unSetTower()
		{
			if (this.tower != null)
			{
				this.tower = null;
				this.free = true;
			}
		}
		public void setTower(Tower tower)
		{
			if (this.free)
			{
				this.tower = tower;
				this.free = false;
			}
		}

		public Tower getTower()
		{
			return this.tower;
		}


		public void setHighlight(highlightType highlight)
		{
			this.highlight = highlight;
		}

		public void setHighlightRange(float range)
		{
			this.highlightRange = range;
			float paintRange = this.highlightRange * this.paintScale;
			float xPaint = this.context.offsetX + this.xFloat * this.paintScale;
			float yPaint = this.context.offsetY + this.yFloat * this.paintScale;
			this.rangeCircle = new EllipseGeometry();
			this.rangeCircle.Center = new Point(xPaint - paintRange, yPaint - paintRange);
			this.rangeCircle.RadiusX = paintRange * 2;
			this.rangeCircle.RadiusY = paintRange * 2;
		}

		public void resetScale()
		{
			this.paintScale = this.context.paintScale;
			float paintX, paintY;

			int shift = this.y & 1;
			this.wFloat = (float)Math.Sin(Math.PI / 3);
			this.xFloat = this.wFloat + this.x * this.wFloat * 2 + shift * this.wFloat;
			this.yFloat = 1.5f * this.y + 1;

			this.wPaint = this.wFloat * this.paintScale;
			this.xPaint = this.context.offsetX + this.xFloat * this.paintScale;
			this.yPaint = this.context.offsetY + this.yFloat * this.paintScale;

			this.points = util.Geometry.createPolyCoords(this.paintScale, xPaint, yPaint);
			this.polyHex = util.Geometry.coordsToGeneralPath(this.points, true);

			GeometryGroup borders = new GeometryGroup();
			//Path borders = new Path();
			//borders.Data = borders;

			Hex[,] grid = this.context.grid;
			if (this.x < (this.context.gridWidth - (this.y % 2) - 1) && grid[this.x + 1, this.y].getType() == HexBase.PATH)
			{
				// Right is empty
				LineGeometry tempLine = new LineGeometry();
				tempLine.StartPoint = new Point(xPaint + this.wPaint, yPaint - paintScale / 2);
				tempLine.EndPoint = new Point(xPaint + this.wPaint, yPaint + paintScale / 2);
				borders.Children.Add(tempLine);
			}

			if (this.y > 0 && this.x + (this.y & 1) <= (this.context.gridWidth - ((this.y - 1) & 1) - 1) && (grid[this.x + (this.y & 1), this.y - 1].getType() == HexBase.PATH))
			{
				// Right-Up is empty
				LineGeometry tempLine = new LineGeometry();
				tempLine.StartPoint = new Point(xPaint + 0, yPaint - paintScale);
				tempLine.EndPoint = new Point(xPaint + this.wPaint, yPaint - paintScale / 2);
				borders.Children.Add(tempLine);
			}

			if (this.y < this.context.gridHeight - 1 && this.x + (this.y & 1) <= (this.context.gridWidth - ((this.y + 1) & 1) - 1) && (grid[this.x + (this.y & 1), this.y + 1].getType() == HexBase.PATH))
			{
				// Right-Down is empty
				LineGeometry tempLine = new LineGeometry();
				tempLine.StartPoint = new Point(xPaint + 0, yPaint + paintScale);
				tempLine.EndPoint = new Point(xPaint + this.wPaint, yPaint + paintScale / 2);
				borders.Children.Add(tempLine);
			}


			if ((this.x > 0) && (grid[this.x - 1, this.y].getType() == HexBase.PATH))
			{
				// Left is empty
				LineGeometry tempLine = new LineGeometry();
				tempLine.StartPoint = new Point(xPaint - this.wPaint, yPaint - paintScale / 2);
				tempLine.EndPoint = new Point(xPaint - this.wPaint, yPaint - paintScale / 2);
				borders.Children.Add(tempLine);
			}

			if (this.y > 0 && this.x - ((this.y + 1) & 1) >= 0 && (grid[this.x - ((this.y + 1) & 1), this.y - 1].getType() == HexBase.PATH))
			{
				// Left-Up is empty
				LineGeometry tempLine = new LineGeometry();
				tempLine.StartPoint = new Point(xPaint + 0, yPaint - paintScale);
				tempLine.EndPoint = new Point(xPaint + 0, yPaint - paintScale);
				borders.Children.Add(tempLine);
			}
			if (this.y < this.context.gridHeight - 1 && this.x - ((this.y + 1) & 1) >= 0 && (grid[this.x - ((this.y + 1) & 1), this.y + 1].getType() == HexBase.PATH))
			{
				// Left-Down is empty
				LineGeometry tempLine = new LineGeometry();
				tempLine.StartPoint = new Point(xPaint + 0, yPaint + paintScale);
				tempLine.EndPoint = new Point(xPaint + 0, yPaint + paintScale);
				borders.Children.Add(tempLine);
			}

			this.bordersE = borders;

#if PORT
			this.stroke1 = new Brush(1.0f * this.context.strokeScale, Brush.CAP_ROUND, Brush.JOIN_BEVEL);
			this.stroke2 = new Brush(3.0f * this.context.strokeScale, Brush.CAP_ROUND, Brush.JOIN_ROUND);
#endif

			float paintRange = this.highlightRange * this.paintScale;
			this.rangeCircle = new EllipseGeometry();
			this.rangeCircle.Center = new Point(xPaint, yPaint);
			this.rangeCircle.RadiusX = paintRange;
			this.rangeCircle.RadiusY = paintRange;
		}

		public void paintRangeCircle(Canvas g2)
		{
			Path path = new Path();
			path.Data = this.rangeCircle;
			path.Stroke = new SolidColorBrush(this.rangeColor);
			g2.Children.Add(path);
		}

		public virtual void paintBase(Canvas g2_0, Canvas g2_1)
		{
			this.polyHex.Stroke = new SolidColorBrush(this.borderEmptyColor);
			this.polyHex.StrokeThickness = 1;
			this.polyHex.Fill = new SolidColorBrush(this.fillColor);
			g2_0.Children.Add(this.polyHex);

			Path path = new Path();
			path.Data = this.bordersE;
			path.Stroke = new SolidColorBrush(this.borderEmptyColor);
			g2_0.Children.Add(path);
		}

		public virtual void paintEffects(Canvas g2)
		{
			switch (this.highlight)
			{
				case highlightType.placeTower:
					if (this.free)
					{
#if PORT
						g2.setColor(this.highlightOK);
#endif
						this.paintRangeCircle(g2);
					}
					else
					{
#if PORT
						g2.setColor(this.highlightNOK);
#endif
						this.paintRangeCircle(g2);
					}
#if PORT
					g2.fill(this.polyHex);
#endif
					break;
				case highlightType.editHex:
#if PORT
					g2.setColor(this.highlightOK);
					g2.fill(this.polyHex);
#endif
					break;
				case highlightType.selectTower:
#if PORT
					g2.setColor(this.highlightOK);
					g2.fill(this.polyHex);
#endif
					break;
			}
		}

		public char getShortName()
		{
			return this.shortName;
		}

		public int getType()
		{
			return type;
		}

		public bool isFree()
		{
			return free;
		}
	}
}
